package com.silverhaze.diamond.client.ui.dialogs;

import com.silverhaze.commons.db.datasource.ObjectEntity;
import com.silverhaze.commons.utils.crypt.MD5;
import com.silverhaze.diamond.client.Application;
import com.silverhaze.diamond.client.data.dao.DAOLocator;
import com.silverhaze.diamond.client.resources.ServiceResourceContainer;
import com.silverhaze.diamond.client.settings.SettingsStorage;
import com.silverhaze.diamond.client.ui.UIHelper;
import com.silverhaze.diamond.client.ui.UIStringConstants;
import com.silverhaze.diamond.client.utils.ServiceException;
import com.silverhaze.diamond.client.utils.db.ServiceDataSource;
import com.silverhaze.diamond.common.entity.SystemUser;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Date;
import java.util.List;

/**
 * Author: Ivan Babanin
 * ? Lizard Software, 2007 y.
 */
public class LoginDialog extends AbstractDialog {

    private static final String KEY_PHRASE = "z1x2c3v4b5n6m7,8.9";

    private JTextField loginField;
    private JPasswordField passwordField;

    private JCheckBox savePasswordCheckBox;

    private static LoginDialog loginDlg;

    public LoginDialog(Frame owner, boolean modal, SystemUser loginUser) {
        super(owner, modal);

        if (loginUser == null) {
            throw new ServiceException("internal error: loginUser is NULL");
        }
        this.setLoginUser(loginUser);

        setTitle(UIHelper.getCaption() + " - Авторизация");
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                Application.finish();
            }
        });
    }

    private void setLoginUser(SystemUser loginUser) {

    }

    protected void init(DialogButtonView viewType) {
        super.init(viewType);

        loginField = new JTextField(20);
        passwordField = new JPasswordField(20);
        savePasswordCheckBox = new JCheckBox("сохранить пароль");

        String settingsPassword = SettingsStorage.getSettings().getPassword();
        if (!"".equals(settingsPassword) && settingsPassword != null) {
            passwordField.setText(decrypt(settingsPassword));
            savePasswordCheckBox.setSelected(true);
        }


        this.addKeyListener(new EnterListener());
        loginField.addKeyListener(new EnterListener());
        passwordField.addKeyListener(new EnterListener());

        loginField.setText(SettingsStorage.getSettings().getUiSettings().getLastLoginName());

        JButton loginBtn = new JButton(UIStringConstants.ENTER);
        loginBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                okPressed();
            }
        });

        JButton cancelBtn = new JButton(UIStringConstants.CANCEL);
        cancelBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Application.finish();
            }
        });

        JPanel formPanel = new JPanel(new BorderLayout());

        formPanel.add(UIHelper.createGridPanel(5, 5, 5, 5, 3, 2,
                UIStringConstants.LOGIN + ": ", loginField,
                UIStringConstants.PASSWORD + ": ", passwordField,
                "", savePasswordCheckBox));

        JLabel jLabel = new JLabel(ServiceResourceContainer.AUTHORIZATION_SCREEN);
        Box vTopBox = Box.createVerticalBox();
        vTopBox.add(jLabel);
        vTopBox.add(Box.createVerticalStrut(10));

        Box vBottomBox = Box.createVerticalBox();
        vBottomBox.add(Box.createVerticalStrut(5));

        getContent().add(new JLabel(ServiceResourceContainer.IMAGE), BorderLayout.NORTH);
        getContent().add(formPanel, BorderLayout.CENTER);
        getContent().add(UIHelper.packInPanel(UIHelper.hBox(loginBtn, 2, cancelBtn), BorderLayout.LINE_END), BorderLayout.SOUTH);

        getRootPane().setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

        pack();
    }

    protected void okPressed() {
        String login = loginField.getText().trim();
        String ipassword = new String(passwordField.getPassword());

        if (ipassword.length() != 0) {
            String password = MD5.crypt(ipassword);

            SystemUser logUser;
            if (!login.equals("")) {
                logUser = findLoginUser(login, password);
            } else {
                logUser = null;
                Dialogs.showErrorDialog(LoginDialog.this, UIStringConstants.ENTER_LOGIN);
            }

            if (logUser != null) {
                getErrorPanel().clearErrorText();
                logUser.setLastLogin(new Date());
                SettingsStorage.getSettings().getUiSettings().setLastLoginName(login);
                SettingsStorage.getUserSettings().setCurrentUser(logUser);
                ServiceDataSource.getInstance().update(logUser);

                if (savePasswordCheckBox.isSelected()) {
                    SettingsStorage.getSettings().setPassword(encrypt(ipassword));
                } else {
                    SettingsStorage.getSettings().setPassword("");
                }

                loginSuccesfull();
            } else {
                getErrorPanel().setErrorText(UIStringConstants.NO_USER_WITH_SUCH_LOGIN_PASS);
            }
        } else {
            getErrorPanel().setErrorText(UIStringConstants.EMPTY_PASSWORD);
        }
    }

    protected void cancelPressed() {

    }

    private SystemUser findLoginUser(String login, String password) {
        List<ObjectEntity> users = DAOLocator.getInstance().getUsers();

        for (ObjectEntity oe : users) {
            SystemUser u = (SystemUser) oe;

            if (login.equals(u.getLogin()) && password.equals(u.getPassword())) {
                return u;
            }
        }

        return null;
    }

    private void loginSuccesfull() {
        passwordField.setText("");
        setVisible(false);
    }

    protected String getCaption() {
        return UIHelper.getCaption() + " - " + UIStringConstants.AUTHORIZATION;
    }

    public static void showDialog(Frame parent, SystemUser loginUser) {
        if (loginDlg == null) {
            loginDlg = new LoginDialog(parent, true, loginUser);
        } else {
            loginDlg.setLoginUser(loginUser);
        }

        loginDlg.setVisible(true);
    }

    private String encrypt(String password) {
        try {
            BASE64Encoder encoder = new BASE64Encoder();
            DESKeySpec keySpec = new DESKeySpec(KEY_PHRASE.getBytes("UTF8"));
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey key = keyFactory.generateSecret(keySpec);

            byte[] cleartext = password.getBytes("UTF8");

            Cipher cipher = Cipher.getInstance("DES"); // cipher is not thread safe
            cipher.init(Cipher.ENCRYPT_MODE, key);

            return encoder.encode(cipher.doFinal(cleartext));
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }

        return "";
    }

    private String decrypt(String password) {
        if ("".equals(password)) {
            return "";
        }

        try {
            BASE64Decoder decoder = new BASE64Decoder();

            DESKeySpec keySpec = new DESKeySpec(KEY_PHRASE.getBytes("UTF8"));
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey key = keyFactory.generateSecret(keySpec);
            byte[] encrypedPwdBytes = decoder.decodeBuffer(password);

            Cipher cipher = Cipher.getInstance("DES");// cipher is not thread safe
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] plainTextPwdBytes = (cipher.doFinal(encrypedPwdBytes));

            return new String(plainTextPwdBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "";
    }
}

